const https = require('https');
const fs = require('fs');
var path = require('path');
const tls = require('tls');
const crypto = require('crypto');

function sha256(s) {
    return crypto.createHash('sha256').update(s).digest('base64');
}

let keys = "keys";
let public_key = ""//可以用来加密通信
const options = {
    // hostname: '127.0.0.1',
    hostname: 'localhost',//与证中的一致
    port: 8001,
    path: '/',
    method: 'GET',
    // 客户端私钥
    key: fs.readFileSync(path.resolve(__dirname, keys,'client.pri')),
    // 客户端证书
    cert: fs.readFileSync(path.join(__dirname,keys, 'client.crt')),
    // client 端到 CA 签名
    ca: [fs.readFileSync(path.join(__dirname, keys,'ca.crt'))],
    agent: false,
    // 开启双向认证
    rejectUnauthorized: true,
    checkServerIdentity: function (host, cert) {
        // 确保将证书颁发给所连接的主机。
        const err = tls.checkServerIdentity(host, cert);
        if (err) {
            return err;
        }

        // 固定公钥，类似于固定的 HPKP pin-sha25。
        const pubkey256 = 'TuOGwr8LevvniS5mUxDnINYO6FmoRFCdS3tkAM8f7GA=';
        //服务器的公钥
        let pubkey_server_base64 = cert.pubkey.toString('base64');
        public_key = pubkey_server_base64
        const pubkey_sha256 = sha256(pubkey_server_base64)
        if (pubkey_sha256 !== pubkey256) {
            const msg = '证书验证错误: ' +
                `'${cert.subject.CN}' 的公钥` +
                '与固定的指纹不符';
            return new Error(msg);
        }

        // 固定确切的证书，而不是公钥。证书的指纹,可以从证书上看到
        const cert256 = '4D:54:E7:EC:D8:D7:0C:67:9C:E1:27:3C:92:F6:26:E7:08:51:E1:14:02:4A:D9:2B:E2:B7:F9:D5:A3:74:11:F6';
        if (cert.fingerprint256 !== cert256) {
            const msg = '证书验证错误: ' +
                `'${cert.subject.CN}' 的证书` +
                '与固定的指纹不符';
            return new Error(msg);
        }

        // 此循环仅供参考。
        // 打印链条中所有证书的证书与公钥指纹。
        // 通常，将发行人的公钥固定在公共互联网上，同时将服务的公钥固定在私密的环境中。
        do {
            console.log('主体的常用名称:', cert.subject.CN);
            console.log('  证书的 SHA256 指纹:', cert.fingerprint256);
            console.log('  服务器公钥:', cert.pubkey.toString('base64'));

            hash = crypto.createHash('sha256');
            console.log('  公钥的 ping-sha256:', sha256(cert.pubkey));

            lastprint256 = cert.fingerprint256;
            cert = cert.issuerCertificate;
        } while (cert.fingerprint256 !== lastprint256);

    },
};

// console.log(options.cert.toString())
options.agent = new https.Agent(options);
const req = https.request(options, ( res) => {
    console.log('client connected', res.connection.authorized ? 'authorized' : 'unauthorized');
    console.log('状态码:', res.statusCode);
    res.setEncoding('utf-8');
    res.on('data', (d) => {
        process.stdout.write(d);
    });
});

req.on('error', (e) => {
    console.error(e);
});

req.end();